<script setup lang="ts">
import { onMounted, reactive, h, computed, ref } from 'vue';
import { RouterLink } from 'vue-router';
import { DataTableColumns, NButton, NDataTable, useMessage, NText, NP, NInputNumber } from 'naive-ui';
import { getCartItems, modifyItemInCart, removeItemFromCart, setCheckedCart } from '../util/cart';
import statusCode from '../api/statusCode';
import { queryGoodsInfo } from '../api/goods';
import router from '../router';

const message = useMessage();

const items = computed(() => getCartItems());

type TableItem = { storeId: number; storeName: string; productId: number; productName: string; attributeId: number; unitPrice: number; quantity: number; color: string; stock: number; }
const tableItems = reactive<TableItem[]>([]);

const loading = ref(false);

const getCart = () => {
  loading.value = true;

  tableItems.length = 0;
  const promises = [] as ReturnType<typeof getGoodsInfo>[];
  items.value.forEach(i => {
    const p = getGoodsInfo(i.productId);
      p
      .then(info => {
        if (info) {
          const attr = info.info.find(attr => attr.attributeId == i.attributeId);
          if (!attr) throw new Error(`无法找到id为${info.productId}的属性${i.attributeId}`);
          tableItems.push({
            storeId: info.storeId,
            storeName: info.storeName,
            productId: info.productId,
            productName: info.productName,
            attributeId: attr.attributeId,
            color: attr.color,
            unitPrice: attr.unitPrice,
            quantity: i.quantity,
            stock: attr.stock
          });
        }
      })
      .catch(err => message.error('' + err));
    promises.push(p);
  });
  Promise.allSettled(promises)
  .then(() => {
    loading.value = false;
    tableItems.sort((a, b) => a.attributeId - b.attributeId);
  });
};

const getGoodsInfo = async (productId: number) => {
  try {
    const resp = await queryGoodsInfo(productId);
    if (resp.status === statusCode.SUCCESS) {
      return resp.data;
    } else {
      throw new Error(`查找id为${productId}的产品信息时出错`);
    }
  } catch (error) {
    message.error('' + error);
    return null;
  }
};

const columns: DataTableColumns<TableItem> = [
  {
    type: 'selection'
  },
  {
    title: '商店',
    key: 'storeName',
    render(row) {
      return h(
        RouterLink,
        {
          to: {
            name: 'store',
            params: {
              storeId: row.storeId
            }
          },
          class: 'link'
        },
        { default: () => row.storeName }
      );
    }
  },
  {
    title: '商品',
    key: 'productName',
    render(row) {
      return h(
        RouterLink,
        {
          to: {
            name: 'product',
            params: {
              storeId: row.storeId,
              productId: row.productId
            } 
          },
          class: 'link'
        },
        { default: () => row.productName }
      );
    }
  },
  {
    title: '颜色',
    key: 'color'
  },
  {
    title: '单价',
    key: 'unitPrice',
    render(row) {
      return h('span', {}, { default: () => '￥' + row.unitPrice });
    }
  },
  {
    className: 'quantity-row',
    title: '数量',
    key: 'quantity',
    render(row) {
      return h(
        NInputNumber,
        {
          value: row.quantity,
          min: 0,
          max: row.stock,
          clearable: true,
          onUpdateValue: (v) => {
            modifyItemInCart({
              storeId: row.storeId,
              productId: row.productId,
              attributeId: row.attributeId,
              quantity: v ?? 0
            });
            getCart();
          }
        }
      );
    }
  },
  {
    title: '小计',
    key: 'total',
    render(row) {
      return h('span', { style: { fontWeight: 'bolder' } }, { default: () => '￥' + (row.unitPrice * row.quantity).toFixed(2) });
    }
  },
  {
    title: '操作',
    key: 'actions',
    render(row) {
      return h(
        NButton,
        {
          type: 'error',
          size: 'small',
          onClick: () => {
            if (removeItemFromCart({
              storeId: row.storeId,
              productId: row.productId,
              attributeId: row.attributeId
            })) message.success(`删除了颜色为${row.color}的${row.productName}`);
            else message.error(`无法删除颜色为${row.color}的${row.productName}`);
            getCart(); // fixme: there should be a better way than this
          }
        },
        { default: () => '删除' }
      )
    }
  }
];

onMounted(getCart);

const totalPrice =
  computed(() =>
    tableItems
    .filter(
      i =>
      checkedRowKeys.some(attrId => attrId == i.attributeId)
    )
    .reduce(
      (accumulateVal, item) =>
        accumulateVal + (item.unitPrice * item.quantity),
        0
    )
    .toFixed(2)
  );

const checkedRowKeys = reactive<(string | number)[]>([]);

const handleCheck = (rowKeys: (string | number)[]) => {
  checkedRowKeys.length = 0;
  checkedRowKeys.push(...rowKeys);
};

const checkedItems =
  computed(() =>
    items.value
      .filter(item =>
        checkedRowKeys.some(attrId => item.attributeId == attrId)
      )
  );

const handleClickBtn = () => {
  setCheckedCart(checkedItems.value);
  checkedItems.value.forEach(item => removeItemFromCart(item));
  router.push({ name: 'placeOrder' });
};

</script>

<template>
  <p>购物车</p>
  <n-data-table
    :loading="loading"
    :data="tableItems"
    :columns="columns"
    :row-key="row => row.attributeId"
    @update:checked-row-keys="handleCheck"
  />

  <n-p>
    总价：
    <n-text
      class="total-price price"
      type="error" 
      depth="1"
      strong
    >
      {{ totalPrice }}
    </n-text>
  </n-p>
  <n-button
    type="primary"
    @click="handleClickBtn"
    :disabled="checkedRowKeys.length == 0"
  >
    去结算
  </n-button>
</template>

<style scoped>
.price::before {
  content: "￥";
}
.price {
  color: rgb(232, 59, 51);
  font-weight: bolder;
  font-size: 24px;
}

::v-deep(.quantity-row) {
  max-width: 5em !important;
}
</style>
